package com.wrench.elevator.util;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.fileupload.FileUpload;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.elevatorbus.banshou.mina.FileUploadRequest;
import com.wrench.elevator.constant.Dict;
import com.wrench.elevator.jedis.JedisChengtiUtil;
import com.wrench.elevator.jedis.JedisFileUploadRequestUtil;

/**
 * @Description: 工具类
 * @author yangchenfeng
 * @date Oct 13, 2017 2:03:26 PM
 * @version V1.0
 */
public abstract class WrenchUtil
{
    private static final Logger logger = LoggerFactory.getLogger(WrenchUtil.class);
    
    /**
     * 
     * 校验手机号码的正则表达式
     * 
     */
    public static final String PHONE_REGEX = "^((1[3,5,8][0-9])|(14[5,7])|(17[0,6,7,8])|(19[7]))\\d{8}$";
    
    /**
     * 校验是否是正整数的正则表达式
     */
    public static final String INT_REGEX = "^\\+*\\d+$";
    
    /**
     * 判断是否是小数的正则表达式
     * */
    public static final String DOUBLE_REGEX = "^\\d+(\\.\\d{1,2})$";
    
    /**
     * 时间格式
     * */
    public static final String TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    
    /**
     * base url
     * */
    public static final String BASE_URL = "http://114.80.100.145:8887/";
    
    /**
     * add person
     * */
    public static final String ADD_PERSON = "groups/add_person";
    
    /**
     * create group
     * */
    public static final String CREATE_GROUP = "groups/create";
    
    /**
     * api_id
     * */
    public static final String API_ID = "2d951c11cef8bb6c52941e6569d69c3a";
    
    /**
     * api_secret
     * */
    public static final String API_SECRET = "ce998a37a16a73b87624aab95bbbb94300671d71";
    
    public static final Charset charset = Charset.forName("UTF-8");// 设置编码
    
    /*
     * 是否有null对象
     */
    public static boolean hasNull(Object... objects)
    {
        for (Object object : objects)
        {
            if (object == null)
                return true;
        }
        return false;
    }
    
    /**
     * 判断字符串中间是否有空格
     */
    public static boolean hasBlank(String... strings)
    {
        for (String string : strings)
        {
            if (string.indexOf(" ") > 0)
                return true;
        }
        return false;
    }
    
    /**
     * 判断手机格式是否正确
     */
    public static boolean isVaildPhone(String phone)
    {
        return phone.matches(PHONE_REGEX);
    }
    
    /**
     * 响应字符串
     */
    public static void responseStr(HttpServletResponse response, String str)
    {
        PrintWriter out = getWriter(response);
        if (!hasNull(out))
        {
            out.print(str);
        }
    }
    
    /**
     * getWriter()
     */
    private static PrintWriter getWriter(HttpServletResponse response)
    {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = null;
        try
        {
            out = response.getWriter();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            logger.error("==> WrenchUtil.getWriter() -- response.getWriter() Error , error =>{}", e);
        }
        return out;
    }
    
    /**
     * 响应map
     */
    public static void responseMap(HttpServletResponse response, Map<String, Object> map)
    {
        String responseStr = null;
        try
        {
            responseStr = JSON.toJSONString(map);
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            logger.error("==> WrenchUtil.responseMap() -- JSON.toJSONString Error , error =>{}", e);
        }
        if (!hasNull(responseStr))
            responseStr(response, responseStr);
        
    }
    
    /**
     * 字符串拼接
     * 
     */
    public static String concat(String... strings)
    {
        StringBuilder sb = new StringBuilder(strings[0]);
        for (int i = 1; i < strings.length; i++)
        {
            sb.append(strings[i]);
        }
        return sb.toString();
    }
    
    /**
     * 取参数
     */
    public static String getPara(HttpServletRequest request, String paraName)
    {
        try
        {
            request.setCharacterEncoding("utf-8");
        }
        catch (UnsupportedEncodingException e)
        {
            // TODO Auto-generated catch block
            logger.error("==> WrenchUtil.getPara() -- request.setCharacterEncoding Error , error =>{}", e);
        }
        String paraValue = null;
        try
        {
            paraValue = request.getParameter(paraName);
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            logger.error("==> WrenchUtil.getPara() -- request.getParameter Error , error =>{}", e);
        }
        return paraValue;
    }
    
    /**
     * 获取当前时间
     */
    public static String nowTime()
    {
        
        SimpleDateFormat sdf = new SimpleDateFormat(TIME_FORMAT);
        return sdf.format(new Date());
        
    }
    
    /**
     * 判断是否正确的时间格式 yyyy-MM-dd HH:mm:ss
     * */
    public static boolean isVaildTime(String time)
    {
        SimpleDateFormat sdf = new SimpleDateFormat(TIME_FORMAT);
        try
        {
            sdf.parse(time);
            return true;
        }
        catch (ParseException e)
        {
            // TODO Auto-generated catch block
            return false;
        }
    }
    
    /**
     * 判断是否是一个整数
     */
    public static boolean isInt(String str)
    {
        return str.matches(INT_REGEX);
    }
    
    /**
     * 批量判断是否都是整数
     */
    public static boolean areInt(String... strs)
    {
        for (String str : strs)
        {
            if (!isInt(str))
                return false;
        }
        return true;
    }
    
    /**
     * 判断是否是一个小数
     */
    public static boolean isDouble(String str)
    {
        return str.matches(DOUBLE_REGEX);
    }
    
    /**
     * 批量判断是否都是小数
     */
    public static boolean areDouble(String... strs)
    {
        for (String str : strs)
        {
            if (!isInt(str))
                return false;
        }
        return true;
    }
    
    /**
     * 判断性别是否正确
     * */
    public static boolean isVaildGender(String gender)
    {
        return Dict.FACE_GENDER_F.equals(gender) || Dict.FACE_GENDER_M.equals(gender)
            || Dict.FACE_GENDER_UNKNOWN.equals(gender);
    }
    
    /**
     * 判断人脸身份是否正确
     * */
    public static boolean isVaildIdentity(String identity)
    {
        return Dict.FACE_IDENTITY_MASTER.equals(identity) || Dict.FACE_IDENTITY_FAMILY.equals(identity);
    }
    
    /**
     * 判断地址状态是否正确
     * */
    public static boolean isVaildAddressStatus(String address_status)
    {
        return Dict.ADDRESS_ADDRESS_STATUS_USING.equals(address_status)
            || Dict.ADDRESS_ADDRESS_STATUS_DELETED.equals(address_status);
    }
    
    /**
     * 判断两个字符串相等
     * */
    public static boolean stringEquals(String a, String b)
    {
        if (hasNull(a, b))
            return false;
        return a.equals(b);
    }
    
    /**
     * 判断是否是金额数字 整数或者2位内小数
     * */
    public static boolean isMoneyStr(String str)
    {
        return isInt(str) || isDouble(str);
    }
    
    /**
     * 是否已知的设备
     * */
    public static boolean isVaildDevice(String device)
    {
        return Dict.DEVICE_ANDROID.equals(device) || Dict.DEVICE_IOS.equals(device);
    }
    
    /**
     * 获取流水编号
     * */
    public static synchronized String getFlowNo(String head)
    {
        String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String seconds = new SimpleDateFormat("HHmmssSSS").format(new Date());
        
        return head + (date + getEight() + seconds + getTwo());
    }
    
    /**
     * 是否已知的流水类型
     * */
    public static boolean isVaildFlowType(String flow_type)
    {
        return stringEquals(Dict.FLOW_NO_HEAD_CT, flow_type) || stringEquals(Dict.FLOW_NO_HEAD_CZ, flow_type)
            || stringEquals(Dict.FLOW_NO_HEAD_HT, flow_type);
    }
    
    /**
     * 是否已知消费类型
     * */
    public static boolean isVaildConsumeType(String consume_type)
    {
        return stringEquals(Dict.CONSUME_TYPE_CT, consume_type) || stringEquals(Dict.CONSUME_TYPE_HT, consume_type);
    }
    
    /**
     * md5加密
     * */
    public static String md5(String str)
    {
        return DigestUtils.md5Hex(str);
    }
    
    /**
     * 乘梯记录缓存至redis 60s失效 key user_id value {face_id:"face_id",identity:"identity"}
     * */
    public static void cacheChengti(String user_id, String face_id_identity)
    {
        Set<String> value = JedisChengtiUtil.get(user_id);
        if (hasNull(value) || value.size() == 0)
        {
            JedisChengtiUtil.set(user_id, face_id_identity);
            return;
        }
        JedisChengtiUtil.add(user_id, face_id_identity);
    }
    
    /**
     * ios注册时传照片缓存FileUploadRequest
     * */
    public static void cacheFileUploadRequest(FileUploadRequest request)
    {
        JedisFileUploadRequestUtil.set(request.getSessionId(), request);
    }
    
    /**
     * 根据sessionId获取FileUploadRequest
     * */
    public static FileUploadRequest getCacheFileUploadRequest(String sessionId)
    {
        return (FileUploadRequest)JedisFileUploadRequestUtil.get(sessionId);
    }
    
    /**
     * 根据person_id创建group
     * */
    public static String createGroupByPersonId(String person_id, String name)
    {
        MultipartEntity reqEntity = getReqEntity();
        try
        {
            reqEntity.addPart("person_id", new StringBody(person_id, charset));
            reqEntity.addPart("name", new StringBody(name, charset));
        }
        catch (UnsupportedEncodingException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
       JSONObject result = remote(reqEntity, BASE_URL + CREATE_GROUP);
        
        return result.getString("group_id");
    }
    
    /**
     * 把person_id加入到group
     * */
    public static boolean addPersonIdToGroup(String person_id, String group_id)
    {
        MultipartEntity reqEntity = getReqEntity();
        try
        {
            reqEntity.addPart("person_id", new StringBody(person_id, charset));
            reqEntity.addPart("group_id", new StringBody(group_id, charset));
        }
        catch (UnsupportedEncodingException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        JSONObject result = remote(reqEntity, BASE_URL + ADD_PERSON);
        
        return stringEquals(result.getString("status"), "ok");
    }
    
    public static MultipartEntity getReqEntity()
    {
        // 创建要发送的实体，就是key-value的这种结构，借助于这个类，可以实现文件和参数同时上传，很简单的。
        MultipartEntity reqEntity = new MultipartEntity();
        try
        {
            reqEntity.addPart("api_id", new StringBody(API_ID, charset));
            reqEntity.addPart("api_secret", new StringBody(API_SECRET, charset));
        }
        catch (UnsupportedEncodingException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return reqEntity;
        
    }
    
    public static void save(MultipartFile file, String target, HttpServletRequest request,String perfix)
    {
        target = request.getSession().getServletContext().getRealPath(target);
        String fileName = file.getOriginalFilename();
        int pointIndex = fileName.lastIndexOf(".");
        String suffix = fileName.substring(pointIndex);
        File dest = new File(target, perfix+"_"+System.currentTimeMillis() + suffix);
        try
        {
            file.transferTo(dest);
        }
        catch (IllegalStateException | IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        ;
    }
    
    private static JSONObject remote(MultipartEntity reqEntity, String url)
    {
       JSONObject result=null;
        // 1:创建一个httpclient对象
        HttpClient httpclient = new DefaultHttpClient();
        Charset charset = Charset.forName("UTF-8");// 设置编码
        try
        {
            // 2：创建http的发送方式对象，是GET还是post
            HttpPost httppost = new HttpPost(url);
            
            // 3：创建要发送的实体，就是key-value的这种结构，借助于这个类，可以实现文件和参数同时上传，很简单的。
            
            httppost.setEntity(reqEntity);
            
            // 4：执行httppost对象，从而获得信息
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity resEntity = response.getEntity();
            
            // 获得返回来的信息，转化为字符串string
            String resString = EntityUtils.toString(resEntity);
            result = JSON.parseObject(resString);
            
        }
        catch (UnsupportedEncodingException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IllegalStateException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally
        {
            try
            {
                httpclient.getConnectionManager().shutdown();
            }
            catch (Exception ignore)
            {
            }
        }
        return result;
    }
    
    private static String getEight()
    {
        Random rad = new Random();
        
        String result = rad.nextInt(100000000) + "";
        
        if (result.length() == 1)
        {
            result = "0000000" + result;
            return result;
        }
        
        if (result.length() == 2)
        {
            result = "000000" + result;
            return result;
        }
        
        if (result.length() == 3)
        {
            result = "00000" + result;
            return result;
        }
        
        if (result.length() == 4)
        {
            result = "0000" + result;
            return result;
        }
        
        if (result.length() == 5)
        {
            result = "000" + result;
            return result;
        }
        
        if (result.length() == 6)
        {
            result = "00" + result;
            return result;
        }
        
        if (result.length() == 7)
        {
            result = "0" + result;
            return result;
        }
        
        return result;
        
    }
    
    private static String getTwo()
    {
        Random rad = new Random();
        
        String result = rad.nextInt(100) + "";
        
        if (result.length() == 1)
        {
            result = "0" + result;
            return result;
        }
        
        return result;
        
    }
    
}
